package xyz.lwm.lazycat.jdbc.exec;

import org.jetbrains.annotations.NotNull;
import xyz.lwm.lazycat.utility.StringUtil;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;

/**
 * abstract row mapper
 *
 * @author lwm
 * @param <T>
 */
public abstract class RowMapperSupport<T> implements RowMapper<T> {

    @Override
    public T mapRow(@NotNull ResultSet rs, int rowNum) throws SQLException {
        try {

            ResultSetMetaData metaData = rs.getMetaData();
            int columnCount = metaData.getColumnCount();
            RowValue<T> row = createRow(columnCount);
            for (int i = 1; i <= columnCount; i++) {
                String columnName = JdbcUtil.lookupColumnName(metaData, i);
                Object columnValue = getColumnValue(rs, i);
                row.setColumnValue(getColumnName(columnName), columnValue);
            }
            return row.get();

        } catch (Exception e) {
            throw new SQLException(e);
        }
    }

    /**
     * @return wrapper cannot be null
     */
    protected abstract @NotNull RowValue<T> createRow(int columnCount);

    protected String getColumnName(String column) {
        if (column != null && StringUtil.isUnderline((column))) {
            return StringUtil.underlineToCamel(column.toLowerCase());
        }
        return column;
    }

    protected Object getColumnValue(ResultSet rs, int index) throws SQLException {
        return JdbcUtil.getResultSetValue(rs, index);
    }

    protected abstract static class RowValue<T> {

        private final T value;

        protected RowValue(T obj) {
            this.value = obj;
        }

        protected abstract void setColumnValue(String column, Object columnValue);

        protected T get() {
            return value;
        }

    }

}
